-------------------------------------------------------------------------------
-- Title      : MAC Rx module
-- Project    :
-------------------------------------------------------------------------------
-- File       : snk_to_mac.vhd
-- Author     : lihm
-- Company    : Tsinghua
-- Created    : 2015-01-26
-- Last update: 2016-01-26
-- Platform   : Xilinx Virtex 6
-- Standard   : VHDL'93
-------------------------------------------------------------------------------
-- Description: Rx path, data goes from MAC(WRPC) to UDP RX module.
-------------------------------------------------------------------------------
--
-- Copyright (c) 2011 CERN
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE.  See the GNU Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
-- Revisions  :
-- Date        Version  Author          Description
-- 2015-01-26  1.0      lihm            Created
-- 2016-01-26  2.0      lihm            Add more annotation
-- 2016-03-09  3.0      lihm            Rewrite
-------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;

library work;
use work.wr_pkg.all;

entity snk_to_mac is
port (
    clk_sys_i        : in std_logic;
    rst_n_i          : in std_logic;

    snk_i            : in  t_wrf_sink_in;
    snk_o            : out t_wrf_sink_out;
    mac_rx_data      : out std_logic_vector(15 downto 0);
    mac_rx_data_valid: out std_logic;
    mac_rx_sof       : out std_logic;
    mac_rx_eof       : out std_logic
);
end snk_to_mac;

architecture rtl of snk_to_mac is

signal snk_out: t_wrf_sink_out;

signal dvalid :std_logic;
signal data:std_logic_vector(15 downto 0);

type t_state is(T_IDLE,T_START,T_DATA,T_END);
signal state : t_state;

function f_b2s (x : boolean)
    return std_logic is
begin
    if(x) then
        return '1';
    else
        return '0';
    end if;
end function;

begin  -- rtl

snk_o         <= snk_out;
snk_out.stall <= '0';
snk_out.err   <= '0';
snk_out.rty   <= '0';

p_gen_ack : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
    if rst_n_i = '0' then
        snk_out.ack <= '0';
    else
        snk_out.ack <= snk_i.cyc and snk_i.stb and snk_i.we and not snk_out.stall;
    end if;
end if;
end process;

dvalid <= f_b2s(snk_i.adr=C_WRF_DATA) and snk_i.cyc and snk_i.stb;-- data valid

p_data_latch : process( clk_sys_i )
begin
    if rising_edge(clk_sys_i) then
        if rst_n_i='0' then
            data <= (others=>'0');
        else
            if dvalid = '1' then
                data <= snk_i.dat;
            end if ;
        end if ;
    end if ;
end process ; -- p_data_latch

p_rd_fsm: process (clk_sys_i)
begin
 if rising_edge(clk_sys_i) then
    if rst_n_i = '0' then
        mac_rx_sof <= '0';
        mac_rx_eof <= '0';
        mac_rx_data_valid <='0';
        mac_rx_data <= (others=>'0');
    else
        case( state ) is
            when T_IDLE =>
                mac_rx_sof <= '0';
                mac_rx_eof <= '0';
                mac_rx_data_valid <= '0';
                mac_rx_data <= (others=>'0');

                if dvalid = '1' then
                    state <= T_START;
                end if ;

            when T_START =>
                mac_rx_sof <= '1';
                mac_rx_eof <= '0';
                mac_rx_data_valid <= '1';
                mac_rx_data <= data;
                state <= T_DATA;

            when T_DATA =>
                mac_rx_sof <= '0';
                mac_rx_eof <= '0';
                mac_rx_data_valid <= '1';
                mac_rx_data <= data;
                if dvalid = '0' then
                    mac_rx_eof <= '1';
                    state <= T_END;
                end if ;

            when T_END =>
                mac_rx_sof <= '0';
                mac_rx_eof <= '0';
                mac_rx_data_valid <= '0';
                mac_rx_data <= data;
                if dvalid = '0' then
                    state <= T_IDLE;
                else
                    state <= T_START;        
                end if ;
                

            when others =>
                state <= T_IDLE;
        end case ;
    end if ;
end if ;
end process;

end rtl;
